package com.zn.loading
{
    import com.zn.log.Log;
    import com.zn.utils.UIDUtil;
    
    import flash.events.Event;
    import flash.events.EventDispatcher;
    import flash.events.IOErrorEvent;
    import flash.events.ProgressEvent;
    import flash.net.URLRequest;
    import flash.utils.clearInterval;
    import flash.utils.getTimer;
    import flash.utils.setInterval;
    import flash.utils.setTimeout;


    [Event(name="complete", type="flash.events.Event")]
    [Event(name="progress", type="flash.events.ProgressEvent")]
    [Event(name="ioError", type="flash.events.IOErrorEvent")]
    [Event(name="open", type="flash.events.Event")]
    public class LoaderItem extends EventDispatcher
    {
        protected static var _types:Object = {};

        protected static var _isParseLoaders:Boolean = false;

		public static var maxCheckProgressTime:int=1000*60*3;
		
		private static var _waitLoaderList:Array=[];
		
		private static var _currentLoader:LoaderItem;
		
        private var _loaderStatus:int = LoaderStatus.READY;

        private var _url:String = "";

        private var _name:String = "";

        private var _loaderXML:XML;

        protected var _bytesTotal:uint;

        protected var _bytesLoaded:uint;

        protected var _content:Object;

        protected var _version:int = -1;

        public var noCache:Boolean = true;

        protected var _urlRequest:URLRequest;

        private var _checkProgressIntervalID:int;

        private var _lastCheckTime:int;

        public function LoaderItem(url:String = null, name:String = null)
        {
            super();

            this.url = url;
            if (url)
                _urlRequest = new URLRequest(url);

            if (!name)
                this.name = UIDUtil.createUID();
            else
                this.name = name;

            init();
        }

        protected static function _activeTypes(name:String, typeClass:Class):void
        {
            _types[name] = typeClass;
        }

        protected function init():void
        {
        }

        public function load(flush:Boolean = false):void
        {
			
			if(_currentLoader!=null && _currentLoader!=this)
				_currentLoader.pause();
			
			_currentLoader=this;
			
            _loaderStatus = LoaderStatus.LOADING;
            prepRequest();
			
			_lastCheckTime=getTimer();
			clearInterval(_checkProgressIntervalID);
			if(this is LoaderMax)
				return ;
			
			_checkProgressIntervalID=setInterval(checkProgress,100);
        }

		private function cleanCheckProgress():void
		{
			clearInterval(_checkProgressIntervalID);
		}

		
		private function checkProgress():void
		{
			if(_loaderStatus==LoaderStatus.LOADING)
			{
				//加载中断，重新加载这个文件
				var t:int=getTimer();
				var d:int=t-_lastCheckTime;
					
				if(d>maxCheckProgressTime)
				{
					var event:IOErrorEvent=new IOErrorEvent(IOErrorEvent.IO_ERROR,false,false,"加载错误");
					ioErrorHandler(event);
				}
			}
		}
		
        protected function completeHandler(event:Event):void
        {
			cleanCheckProgress();
			
			loaderWait();
        }

        protected function progressHandler(evnet:ProgressEvent):void
        {
			_lastCheckTime=getTimer();
            _bytesLoaded = evnet.bytesLoaded;
            _bytesTotal = evnet.bytesTotal;

            dispatchEvent(new LoaderEvent(LoaderEvent.PROGRESS, this, _bytesLoaded, _bytesTotal));
        }

        protected function ioErrorHandler(event:IOErrorEvent):void
        {
			cleanCheckProgress();

			loaderWait();
			
            _loaderStatus = LoaderStatus.FAILED;
            Log.debug(LoaderItem, "ioErrorHandler", event.text);
            dispatchEvent(new LoaderEvent(LoaderEvent.IO_ERROR,this));
			//throw new Error("加载资源错误："+url);
        }

        public function get loaderStatus():int
        {
            return _loaderStatus;
        }

        public function set loaderStatus(value:int):void
        {
            _loaderStatus = value;
        }

        public function get url():String
        {
            return _url;
        }

        public function set url(value:String):void
        {
            LoaderMax.removeLoaderItem(_url, false);
            _url = value;
            LoaderMax.addLoaderItem(this);
        }

        public function get name():String
        {
            return _name;
        }

        public function set name(value:String):void
        {
            LoaderMax.removeLoaderItem(_name, false);

            _name = value;

            LoaderMax.addLoaderItem(this);
        }

        public function get loaderXML():XML
        {
            return _loaderXML;
        }

        public function set loaderXML(value:XML):void
        {
            _loaderXML = value;

            if (loaderXML.hasOwnProperty("@name"))
                name = loaderXML.@name;
            else
                name = UIDUtil.createUID();

            if (loaderXML.hasOwnProperty("@url"))
            {
                url = loaderXML.@url;
                _urlRequest = new URLRequest(url);
            }

            if (loaderXML.hasOwnProperty("@noCache"))
                noCache = loaderXML.@noCache;

            if (loaderXML.hasOwnProperty("@version"))
                _version = loaderXML.@version;
        }

        public function get content():Object
        {
            return _content;
        }

        public function get bytesTotal():uint
        {
            return _bytesTotal;
        }

        public function get bytesLoaded():uint
        {
            return _bytesLoaded;
        }

        protected function prepRequest():void
        {
            //检查是否启用缓存
            if (_url)
            {
                _urlRequest = LoaderMax.getURLRequest(_url, noCache, _version);
            }
        }

        public function unload():void
        {
			cleanCheckProgress();
		
			loaderWait();
			
            dispatchEvent(new LoaderEvent(LoaderEvent.LOADER_ITEM_UNLOAD_EVENT,this));
        }

        public function stop():void
        {
			cleanCheckProgress();
			
			loaderWait();
			
            loaderStatus = LoaderStatus.READY;
        }
		
		public function pause():void
		{
			cleanCheckProgress();
			
			_waitLoaderList.push(this);
			loaderStatus = LoaderStatus.READY;
		}
		
		public function loaderWait():void
		{
			_currentLoader=null;
			if(_waitLoaderList.length>0)
			{
				var item:LoaderItem=(_waitLoaderList.pop() as LoaderItem);
				if(item.loaderStatus==LoaderStatus.COMPLETED)
				{
					loaderWait();
					return ;
				}
				
				item.load();
			}
		}
    }
}
